


#ifndef PF_GRAPHIC_H
#define PF_GRAPHIC_H

#include "pf_blocklist.h"
#include "pf_layerlist.h"
#include "pf_variabledict.h"
#include "pf_document.h"
#include "pf_units.h"
#include "lx_Export.h"

class PF_VariableDict;


/**
 * A graphic document which can contain entities layers and blocks.
 *

 */
class LX_EXPORT PF_Graphic : public PF_Document {
public:
    PF_Graphic(PF_Container* parent=NULL);
    virtual ~PF_Graphic();

    //virtual PF_Entity* clone() {
    //	return new PF_Graphic(*this);
    //}

    /** @return LX_Define::EntityGraphic */
    virtual LX_Define::EntityType rtti() const {
        return LX_Define::EntityGraphic;
    }

    virtual unsigned long int countLayerEntities(PF_Layer* layer);

    virtual PF_LayerList* getLayerList() {
        return &layerList;
    }
    virtual PF_BlockList* getBlockList() {
        return &blockList;
    }

    virtual void newDoc();
    virtual bool save(bool isAutoSave = false);
    virtual bool saveAs(const QString& filename, LX_Define::FormatType type);
    virtual bool open(const QString& filename, LX_Define::FormatType type);
	
	// Wrappers for Layer functions:
    void clearLayers() {
		layerList.clear();
	}
    uint countLayers() const {
        return layerList.count();
    }
    PF_Layer* layerAt(uint i) {
        return layerList.at(i);
    }
    void activateLayer(const QString& name) {
		layerList.activate(name);
	}
    void activateLayer(PF_Layer* layer) {
		layerList.activate(layer);
	}
    PF_Layer* getActiveLayer() {
        return layerList.getActive();
    }
    virtual void addLayer(PF_Layer* layer) {
		layerList.add(layer);
	}
    virtual void removeLayer(PF_Layer* layer);
    virtual void editLayer(PF_Layer* layer, const PF_Layer& source) {
		layerList.edit(layer, source);
	}
    PF_Layer* findLayer(const QString& name) {
		return layerList.find(name);
	}
    void toggleLayer(const QString& name) {
		layerList.toggle(name);
	}
    void toggleLayer(PF_Layer* layer) {
		layerList.toggle(layer);
	}
    void toggleLayerLock(PF_Layer* layer) {
		layerList.toggleLock(layer);
	}
    void freezeAllLayers(bool freeze) {
		layerList.freezeAll(freeze);
	}

    void addLayerListListener(PF_LayerListObserver* listener) {
		layerList.addListener(listener);
	}
    void removeLayerListListener(PF_LayerListObserver* listener) {
		layerList.removeListener(listener);
	}


	// Wrapper for block functions:
    void clearBlocks() {
		blockList.clear();
	}
    uint countBlocks() {
        return blockList.count();
    }
    PF_Block* blockAt(uint i) {
        return blockList.at(i);
    }
    void activateBlock(const QString& name) {
		blockList.activate(name);
	}
    void activateBlock(PF_Block* block) {
		blockList.activate(block);
	}
    PF_Block* getActiveBlock() {
        return blockList.getActive();
    }
    virtual bool addBlock(PF_Block* block, bool notify=true) {
		return blockList.add(block, notify);
	}
    virtual void addBlockNotification() {
		blockList.addNotification();
	}
    virtual void removeBlock(PF_Block* block) {
		blockList.remove(block);
	}
    PF_Block* findBlock(const QString& name) {
		return blockList.find(name);
	}
    QString newBlockName() {
		return blockList.newName();
	}
    void toggleBlock(const QString& name) {
		blockList.toggle(name);
	}
    void toggleBlock(PF_Block* block) {
		blockList.toggle(block);
	}
    void freezeAllBlocks(bool freeze) {
		blockList.freezeAll(freeze);
	}
    void addBlockListListener(PF_BlockListObserver* listener) {
		blockList.addListener(listener);
	}
    void removeBlockListListener(PF_BlockListObserver* listener) {
		blockList.removeListener(listener);
	}

	// Wrappers for variable functions:
    void clearVariables() {
		variableDict.clear();
	}
    int countVariables() {
		return variableDict.count();
    }

    void addVariable(const QString& key, const PF_Vector& value, int code) {
		variableDict.add(key, value, code);
	}
    void addVariable(const QString& key, const QString& value, int code) {
		variableDict.add(key, value, code);
	}
    void addVariable(const QString& key, int value, int code) {
		variableDict.add(key, value, code);
	}
    void addVariable(const QString& key, double value, int code) {
		variableDict.add(key, value, code);
	}

    PF_Vector getVariableVector(const QString& key, const PF_Vector& def) {
		return variableDict.getVector(key, def);
	}
    QString getVariableString(const QString& key, const QString& def) {
		return variableDict.getString(key, def);
	}
    int getVariableInt(const QString& key, int def) {
		return variableDict.getInt(key, def);
	}
    double getVariableDouble(const QString& key, double def) {
		return variableDict.getDouble(key, def);
	}

    void removeVariable(const QString& key) {
		variableDict.remove(key);
	}

        QHash<QString, PF_Variable>& getVariableDict() {
		return variableDict.getVariableDict();
	}

	LX_Define::LinearFormat getLinearFormat();
	int getLinearPrecision();
	LX_Define::AngleFormat getAngleFormat();
	int getAnglePrecision();

	PF_Vector getPaperSize();
	void setPaperSize(const PF_Vector& s);
	
	PF_Vector getPaperInsertionBase();
	void setPaperInsertionBase(const PF_Vector& p);
	
	LX_Define::PaperFormat getPaperFormat(bool* landscape);
	void setPaperFormat(LX_Define::PaperFormat f, bool landscape);

	double getPaperScale();
	void setPaperScale(double s);

    virtual void setUnit(LX_Define::Unit u);
    virtual LX_Define::Unit getUnit();

	bool isGridOn();
	void setGridOn(bool on);
	
	bool isDraftOn();
	void setDraftOn(bool on);

    /** Sets the unit of this graphic's dimensions to 'u' */
    /*virtual void setDimensionUnit(LX_Define::Unit u) {
		addVariable("$INSUNITS", (int)u, 70);
        dimensionUnit = u;
    }*/

    /** Gets the unit of this graphic's dimension */
    /*virtual LX_Define::Unit getDimensionUnit() {
        return dimensionUnit;
    }*/

	void centerToPage();
	void fitToPage();
	
	/**
	 * @retval true The document has been modified since it was last saved.
	 * @retval false The document has not been modified since it was last saved.
	 */
    virtual bool isModified() const {
        return modified || layerList.isModified() || blockList.isModified();
    }
	
	/**
	 * Sets the documents modified status to 'm'.
	 */
	virtual void setModified(bool m) {
		modified = m;
		layerList.setModified(m);
		blockList.setModified(m);
	}


    friend std::ostream& operator << (std::ostream& os, PF_Graphic& g);

private:
	PF_LayerList layerList;
	PF_BlockList blockList;
	PF_VariableDict variableDict;

};


#endif
